package iss.java.list;

import com.sun.xml.internal.bind.v2.model.core.ID;
import com.sun.xml.internal.bind.v2.runtime.reflect.NullSafeAccessor;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by wenke on 2016/9/16.
 * // TODO: Modify this class to meet requirement B and C.
 */
public class MyList {
    // two guards. Do not call remove() on them!!
    private Node head;
    private Node tail;
    private int size;
    public static Lock lock=new ReentrantLock();
    private static int userNumber=0;
    private int ID;

    public MyList() {
        ++userNumber;
        ID=userNumber;
        head = new Node(this.ID).setData(0);
        tail = new Node(this.ID).setData(0).setNext(null).setPrev(head);
        head.setNext(tail);
        size = 0;

    }
    public int getID(){return ID;}

    public int getSize() {
        return size;
    }

    public Node getHead() {
        return head;
    }

    public Node getTail() {
        return tail;
    }

    public Node insert(Node _prev, int data) {
        if (_prev.getID() == ID) {
            lock.lock();
            try {
                Node node = new Node(this.ID).setData(data).setNext(_prev.getNext()).setPrev(_prev);
                _prev.getNext().setPrev(node);
                _prev.setNext(node);
                ++size;
                return node;
            } finally {
                lock.unlock();
            }
        }
        else{
            System.out.println("not caller linked list. caller:"+this.getID()+" Node: "+_prev.getID());
            return null;
        }
    }


    public Node remove(Node target) {
        if (target.getID() == ID) {
            lock.lock();
            try {
                if (target == head || target == tail)
                    throw new RuntimeException("DO NOT remove the head or tail node. They are guards.");

                Node prev = target.getPrev();
                Node next = target.getNext();
                prev.setNext(next);
                next.setPrev(prev);
                --size;

                return prev;
            } finally {
                lock.unlock();
            }
        }
        else{
            System.out.println("not caller linked list. caller:"+this.getID()+" Node: "+target.getID());
            return null;
        }
    }

    public void forwardPrint(){
        for (Node n = this.getHead().getNext(); n!=this.getTail(); n=n.getNext()) {
            System.out.printf("%d ", n.getData());
        }
        System.out.println();
    }
    public void backwardPrint(){
        for (Node n = this.getTail().getPrev(); n!=this.getHead(); n=n.getPrev()) {
            System.out.printf("%d ", n.getData());
        }
        System.out.println();
    }

}
